package demo;

import ru.nsu.fit.iconveyor.conveyor.exception.NodeExecutionException;
import ru.nsu.fit.iconveyor.conveyor.node.NodeConnection;
import ru.nsu.fit.iconveyor.conveyor.node.OutputNode;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class ImageWriterNode extends OutputNode {
    public static final String PARAM_OUTPUT_FOLDER_PATH = "output_folder_path";
    private static final String DEFAULT_OUTPUT_FILE_NAME = "out.jpg";
    public static final String INPUT_IMAGE = "input_image";
    private static final String IMAGE_FORMAT = "JPG";
    private static final String OUTPUT_FILE_EXTENSION = ".jpg";

    private final NodeConnection<Image> inputImage;

    public ImageWriterNode(String id) {
        super(id);

        inputImage = new NodeConnection<Image>(Image.class, NodeConnection.Type.INPUT, INPUT_IMAGE);

        addNodeConnection(inputImage);
    }

    @Override
    public Map<String, Object> execute(Map<String, Object> inputBundles, Properties prop) throws NodeExecutionException {
        Image inputImage = (Image)inputBundles.get(INPUT_IMAGE);
        String outputFileName = inputImage.getName();
        if(outputFileName == null) {
            outputFileName = DEFAULT_OUTPUT_FILE_NAME;
        } else {
            int lastDotIndex = outputFileName.lastIndexOf('.');
            if(lastDotIndex >= 0) {
                outputFileName = outputFileName.substring(0, lastDotIndex) + OUTPUT_FILE_EXTENSION;
            } else {
                outputFileName += OUTPUT_FILE_EXTENSION;
            }
        }
        int [][] inputBitmap = inputImage.getBitmap();
        final int imageWidth = inputBitmap.length;
        final int imageHeight = inputBitmap[0].length;


        String outputFolderPath = getParameter(PARAM_OUTPUT_FOLDER_PATH);
        File outputFolder;
        if(outputFolderPath == null) {
            outputFolder = new File("./");
        } else {
            outputFolder = new File(outputFolderPath);
        }
        if(!outputFolder.exists()) {
            outputFolder.mkdirs();
        }

        BufferedImage bufferedImage = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
        for(int x = 0 ; x < imageWidth ; ++x) {
            for(int y = 0 ; y < imageHeight ; ++y) {
                bufferedImage.setRGB(x, y, inputBitmap[x][y]);
            }
        }

        File imageFile = new File(outputFolder, outputFileName);

        try {
            ImageIO.write(bufferedImage, IMAGE_FORMAT, imageFile);
        } catch (IOException e) {
            throw new NodeExecutionException(String.format("Image %s couldn't be written to file %s", inputImage.getName(), outputFileName));
        }

        return new HashMap<String, Object>(0);

    }

    @Override
    public Map<String, Object> preExecute(Map<String, Object> availableInputBundles, Properties prop) {
        if(availableInputBundles.containsKey(INPUT_IMAGE)) {
            return availableInputBundles;
        } else {
            return null;
        }
    }
}
